package com.syher.others.design.proxy.dynamic;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * 缺点： cglib原理是对被代理类生成一个子类
 *        所以被代理的类和方法不能声明为final
 *        私有方法不被代理 
 * @author shenyuhang
 * @date 2018/12/24.
 **/
public class CGLibProxyHandler<T> implements MethodInterceptor {

    public T bind(T target) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(this);
        return (T)enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("before call a method...");
        return proxy.invokeSuper(o, args);
    }

    public static void main(String[] args) {
        RealSubject subject = new CGLibProxyHandler<RealSubject>().bind(new RealSubject());
        subject.doOtherthing();
        subject.doPrivateThing();
        subject.doFinalThing();

        Subject s = new CGLibProxyHandler<Subject>().bind(new RealSubject());
        s.doSomething();
    }

    interface Subject {
        void doSomething();
    }

    static class RealSubject implements Subject {
        @Override
        public void doSomething() {
            System.out.println("doSomething() method has been called.");
        }

        public void doOtherthing() {
            System.out.println("doOtherthing() method has been called.");
        }

        /**
         * 私有方法不走代理
         */
        private void doPrivateThing() {
            System.out.println("doPrivateThing() method has been called.");
        }

        public final void doFinalThing() {
            System.out.println("doFinalThing() method has been called.");
        }
    }
}
